package main

import (
	"fmt"
	"gitee.com/ming369/goinsta"
	"gitee.com/ming369/goinsta/utilities"
	"io"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func main() {

	//uploadVideo()
	//fmt.Println("finish")
	//videoParam := Stat("test.mp4", "out.jpg", "1")
	//fmt.Println(videoParam)
	uploadVideo()
	//uploadAlbum()
}
func uploadAlbum() {
	inst := logIn2()
	//in1 := `./examples/upload-media/test1.jpg`
	//in2 := `./examples/upload-media/test2.jpg`
	//in3 := `./examples/upload-media/test3.jpg`
	f1, _ := os.Open(`./examples/upload-media/03bc1bcd6b555784d8c29012fe4c77d4.jpg`)
	f2, _ := os.Open(`./examples/upload-media/d7de4a32d2b9af8d57927c318e0fc713.jpg`)
	photos := []io.Reader{f1, f2}

	photoCaption := "专柜同步2"
	_, err := inst.UploadAlbum(photos, photoCaption, 0, 0)
	if err != nil {
		fmt.Println(err)
	}
}

func uploadVideo() {
	inst := logIn()

	//in := `./examples/upload-media/6776e3121da054870a031da017f6584f.mp4`
	in := `./examples/upload-media/test.mp4`
	//out := `./examples/upload-video/out.jpg`

	// must 533x533 jpg png
	param, err := Stat(in, "1")
	if err != nil {
		log.Printf("param:%s", err)
		return
	}

	photoCaption := "kaka n#loveme#home"
	param.Quality = 0
	param.FilterType = 0
	item, err := inst.UploadVideo(param, photoCaption)
	if err != nil {
		log.Printf("upload photo faildure:%s", err)
	} else {
		log.Printf("id:%s", item.ID)
	}
	//defer func() {
	//	param.Video.Close()
	//	param.Thumbnail.Close()
	//}()
}

func uploadPhoto() {
	inst := logIn()

	// must 533x533 jpg png
	photoFile, err := os.Open("test.jpg")
	if err != nil {
		log.Printf("file not found:%s", err)
		return
	}
	photoCaption := "jojo n#loveme#home"
	quality := 0
	filterType := 0
	item, err := inst.UploadPhoto(photoFile, photoCaption, quality, filterType)
	if err != nil {
		log.Printf("upload photo faildure:%s", err)
	} else {
		log.Printf("id:%s", item.ID)
	}
}

func logIn() *goinsta.Instagram {

	igLogin := "szlwm001"
	igPassword := "test1234"
	dir, _ := os.Getwd()
	configFile := dir + "/.insta"
	var (
		err   error
		insta *goinsta.Instagram
	)

	if insta, err = goinsta.Import(configFile); err != nil {
		log.Printf("Unable to import Instagram configuration: %s\n", err)
		log.Println("Attempting new login")

		insta = goinsta.New(igLogin, igPassword)
		//insta.SetProxy("http://127.0.0.1:1080", true)
		if err = insta.Login(); err != nil {
			dieOnError("unable to initialize Instagram client: %s", err)
		}
		if err := insta.Export(configFile); err != nil {
			log.Printf("error: unable to export Instagram client configuration: %s\n", err)
		}
	} else {
		//insta.SetProxy("http://127.0.0.1:1080", true)
	}

	return insta
}

func logIn2() *goinsta.Instagram {

	session := "eyJpZCI6MjA1NzY4OTUwOCwidXNlcm5hbWUiOiJzemx3bTAwMSIsImRldmljZV9pZCI6ImFuZHJvaWQtN2RhZThmMDg0MjI4Y2JiZSIsInV1aWQiOiJjZDY5MTQ0MC0zZjVlLTQ4NjUtYjgwOC03OGE2NWViMTM0OTciLCJyYW5rX3Rva2VuIjoiMjA1NzY4OTUwOF9jZDY5MTQ0MC0zZjVlLTQ4NjUtYjgwOC03OGE2NWViMTM0OTciLCJ0b2tlbiI6IjBOeU9nakM0U0ZpMVJtaGVOQU05Z0JzWFM5VHdvckh5IiwicGhvbmVfaWQiOiI3YjNjOWIyYy1mYWQzLTRiM2MtYTU4My1kNDc5ZmY3YmJkMzUiLCJjb29raWVzIjpbeyJOYW1lIjoiY3NyZnRva2VuIiwiVmFsdWUiOiIwTnlPZ2pDNFNGaTFSbWhlTkFNOWdCc1hTOVR3b3JIeSIsIlBhdGgiOiIiLCJEb21haW4iOiIiLCJFeHBpcmVzIjoiMDAwMS0wMS0wMVQwMDowMDowMFoiLCJSYXdFeHBpcmVzIjoiIiwiTWF4QWdlIjowLCJTZWN1cmUiOmZhbHNlLCJIdHRwT25seSI6ZmFsc2UsIlNhbWVTaXRlIjowLCJSYXciOiIiLCJVbnBhcnNlZCI6bnVsbH0seyJOYW1lIjoicnVyIiwiVmFsdWUiOiJGVFciLCJQYXRoIjoiIiwiRG9tYWluIjoiIiwiRXhwaXJlcyI6IjAwMDEtMDEtMDFUMDA6MDA6MDBaIiwiUmF3RXhwaXJlcyI6IiIsIk1heEFnZSI6MCwiU2VjdXJlIjpmYWxzZSwiSHR0cE9ubHkiOmZhbHNlLCJTYW1lU2l0ZSI6MCwiUmF3IjoiIiwiVW5wYXJzZWQiOm51bGx9LHsiTmFtZSI6Im1pZCIsIlZhbHVlIjoiWGJhaUZBQUJBQUZTWlNWM3M1bXhxYWRpTWZaVCIsIlBhdGgiOiIiLCJEb21haW4iOiIiLCJFeHBpcmVzIjoiMDAwMS0wMS0wMVQwMDowMDowMFoiLCJSYXdFeHBpcmVzIjoiIiwiTWF4QWdlIjowLCJTZWN1cmUiOmZhbHNlLCJIdHRwT25seSI6ZmFsc2UsIlNhbWVTaXRlIjowLCJSYXciOiIiLCJVbnBhcnNlZCI6bnVsbH0seyJOYW1lIjoiZHNfdXNlciIsIlZhbHVlIjoic3psd20wMDEiLCJQYXRoIjoiIiwiRG9tYWluIjoiIiwiRXhwaXJlcyI6IjAwMDEtMDEtMDFUMDA6MDA6MDBaIiwiUmF3RXhwaXJlcyI6IiIsIk1heEFnZSI6MCwiU2VjdXJlIjpmYWxzZSwiSHR0cE9ubHkiOmZhbHNlLCJTYW1lU2l0ZSI6MCwiUmF3IjoiIiwiVW5wYXJzZWQiOm51bGx9LHsiTmFtZSI6InNoYmlkIiwiVmFsdWUiOiI0NzUwIiwiUGF0aCI6IiIsIkRvbWFpbiI6IiIsIkV4cGlyZXMiOiIwMDAxLTAxLTAxVDAwOjAwOjAwWiIsIlJhd0V4cGlyZXMiOiIiLCJNYXhBZ2UiOjAsIlNlY3VyZSI6ZmFsc2UsIkh0dHBPbmx5IjpmYWxzZSwiU2FtZVNpdGUiOjAsIlJhdyI6IiIsIlVucGFyc2VkIjpudWxsfSx7Ik5hbWUiOiJzaGJ0cyIsIlZhbHVlIjoiMTU3MjI1MDEzNS4wNjcyODk2IiwiUGF0aCI6IiIsIkRvbWFpbiI6IiIsIkV4cGlyZXMiOiIwMDAxLTAxLTAxVDAwOjAwOjAwWiIsIlJhd0V4cGlyZXMiOiIiLCJNYXhBZ2UiOjAsIlNlY3VyZSI6ZmFsc2UsIkh0dHBPbmx5IjpmYWxzZSwiU2FtZVNpdGUiOjAsIlJhdyI6IiIsIlVucGFyc2VkIjpudWxsfSx7Ik5hbWUiOiJkc191c2VyX2lkIiwiVmFsdWUiOiIyMDU3Njg5NTA4IiwiUGF0aCI6IiIsIkRvbWFpbiI6IiIsIkV4cGlyZXMiOiIwMDAxLTAxLTAxVDAwOjAwOjAwWiIsIlJhd0V4cGlyZXMiOiIiLCJNYXhBZ2UiOjAsIlNlY3VyZSI6ZmFsc2UsIkh0dHBPbmx5IjpmYWxzZSwiU2FtZVNpdGUiOjAsIlJhdyI6IiIsIlVucGFyc2VkIjpudWxsfSx7Ik5hbWUiOiJzZXNzaW9uaWQiLCJWYWx1ZSI6IjIwNTc2ODk1MDglM0FlZ3E5Uk5xYzBuTG9pWSUzQTEwIiwiUGF0aCI6IiIsIkRvbWFpbiI6IiIsIkV4cGlyZXMiOiIwMDAxLTAxLTAxVDAwOjAwOjAwWiIsIlJhd0V4cGlyZXMiOiIiLCJNYXhBZ2UiOjAsIlNlY3VyZSI6ZmFsc2UsIkh0dHBPbmx5IjpmYWxzZSwiU2FtZVNpdGUiOjAsIlJhdyI6IiIsIlVucGFyc2VkIjpudWxsfV19"
	var (
		err   error
		insta *goinsta.Instagram
	)

	insta, err = utilities.ImportFromBase64String(session)
	if err != nil {
		fmt.Println(err)
	}

	return insta
}

func dieOnError(format string, a ...interface{}) {
	log.Printf(fmt.Sprintf("error: %s\n", format), a...)
	os.Exit(1)
}

type VideoInfo struct {
	Path     string
	Length   float64 // 时长(s)
	Bitrate  float64 // 播放速率(kb/s)
	Size     int64   // 文件大小(byte)
	Width    int64   // 视频分辨率宽度
	Height   int64   // 视频分辨率高度
	Fps      float64 // 视频帧率(帧/s)
	Vbitrate float64 // 视频比特率(kb/s)
	Abitrate float64 // 音频比特率(kb/s)
	Ahz      float64 // 音频采集率(Hz)
}

// 使用ffmpeg 采集视频信息，并输出一张预览图
// invideo：视频文件地址
// outimage:输出的图片
// 采集的帧位置:建议1-3
func Stat(video, pos string) (*goinsta.VideoParam, error) {

	info, _ := os.Stat(video)
	dir := filepath.Dir(video)
	fileName := info.Name()
	endIndex := strings.LastIndex(fileName, ".")
	imageFile := dir + `\` + info.Name()[:endIndex] + ".jpg"

	// ffmpeg -i in.mp4 -ss 1 -f image2 out.jpg
	cmd := exec.Command("ffmpeg", "-i", video, "-ss", pos, "-f", "image2", imageFile)
	b, _ := cmd.CombinedOutput()

	result := string([]byte(b))
	length, _ := parseDuration(result)
	width, height, _, _ := parseVideo(result)
	//hz, bitrate := parseAudio(result)

	if length == 0 || width == 0 || height == 0 {
		return nil, fmt.Errorf("param is invalid")
	}
	param := goinsta.VideoParam{}
	param.Duration = length
	param.Size = info.Size()
	param.Width = width
	param.Height = height

	param.Video, _ = os.Open(video)
	param.Thumbnail, _ = os.Open(imageFile)
	return &param, nil
}

func getSize(path string) int64 {
	file, _ := os.Stat(path)
	return file.Size()
}

// 解析Duration行
func parseDuration(str string) (float64, float64) {
	regx := regexp.MustCompile(`.*Duration:\s(.*?),.*bitrate:\s(\S+)`)
	s := regx.FindStringSubmatch(str)
	if len(s) != 3 {
		return 0, 0
	}

	t := strings.Split(s[1], ":")
	length := atof64(t[0])*3600 + atof64(t[1])*60 + atof64(t[2])
	return length, atof64(s[2])
}

// 解析Video行
func parseVideo(str string) (int64, int64, float64, float64) {
	regx := regexp.MustCompile(`Stream.*Video.*\s(\d+)x(\d+)(?:.*?(\S+)\skb/s)?.*?(\S+)\sfps`)
	s := regx.FindStringSubmatch(str)

	if len(s) != 5 {
		return 0, 0, 0, 0
	}
	return atoi64(s[1]), atoi64(s[2]), atof64(s[3]), atof64(s[4])
}

func parseAudio(str string) (float64, float64) {
	regx := regexp.MustCompile(`Stream.*Audio.*?(\d+)\sHz.*\s(\S+)\skb/s`)
	s := regx.FindStringSubmatch(str)

	if len(s) != 3 {
		return 0, 0
	}
	return atof64(s[1]), atof64(s[2])
}

func atoi64(s string) int64 {
	i, _ := strconv.ParseInt(s, 10, 64)
	return i
}

func atof64(s string) float64 {
	i, _ := strconv.ParseFloat(s, 64)
	return i
}

func RandString(length int) string {
	rand.Seed(time.Now().UnixNano())
	bytes := make([]byte, length)
	scope := [][]int{{48, 10}, {97, 26}, {65, 26}}
	for i := 0; i < length; i++ {
		k := scope[rand.Intn(3)]
		b := k[0] + rand.Intn(k[1])
		bytes[i] = byte(b)
	}
	return string(bytes)
}
